/// @brief UnionFindSet UFS
#include <algorithm>
#include <cctype>
#include <cstdio>
#include <cstring>
#define int long long
typedef long long ll;

template <typename T>
inline T &read(T &x) {
  x = 0;
  bool f = false;
  short ch = getchar();
  while (!isdigit(ch)) {
    if (ch == '-') f = true;
    ch = getchar();
  }
  while (isdigit(ch)) x = (x << 1) + (x << 3) + (ch ^ '0'), ch = getchar();
  if (f) x = -x;
  return x;
}

const int N = 2e5 + 5, mod = 998244353;
int n, m, f[N], w[N], tag[N];

inline ll qpow(ll base, int exp) {
  ll res = 1;
  while (exp) {
    if (exp & 1) res = res * base % mod;
    base = base * base % mod;
    exp >>= 1;
  }
  return res;
}

const int frac13 = qpow(3, mod - 2), frac23 = 2ll * frac13 % mod,
          frac12 = qpow(2, mod - 2);

int find(int x) {
  if (f[x] == x) return x;
  int fa = find(f[x]);
  if (fa != f[x]) w[x] = (ll)w[x] * w[f[x]] % mod;
  return tag[f[x]] = 1, f[x] = fa;
}

signed main() {
#ifndef ONLINE_JUDGE
#ifdef LOCAL
  freopen64("/tmp/CodeTmp/testdata.in", "r", stdin);
  freopen64("/tmp/CodeTmp/testdata.out", "w", stdout);
#else
  freopen("cong.in", "r", stdin);
  freopen("cong.out", "w", stdout);
#endif
#endif

  read(n), read(m);
  const int all = qpow(3, n);
  for (int i = 1; i <= n; ++i) f[i] = i, w[i] = 1, tag[i] = 1;
  for (int i = 1, opt, u, v; i <= m; ++i) {
    read(opt), read(u);
    if (opt == 1) {
      read(v);
      f[v = find(v)] = (u = find(u));
      w[u] = (ll)w[u] * frac23 % mod;
      w[v] = (ll)w[v] * frac13 % mod;
      w[v] = (ll)w[v] * qpow(w[u], mod - 2) % mod;
    } else {
      int fa = find(u), ans = w[u];
      if (fa != u) ans = (ll)ans * w[fa] % mod;
      printf("%lld\n", (ll)ans * all % mod);
    }
  }
  return 0;
}